package org.hackystat.projecttrajectory.resource.estimate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hackystat.projecttrajectory.resource.estimate.jaxb.ProjectEstimate;

/**
 * Helper class to support ProjectEstimate to String mappings. We need this I
 * don't know how to define JAXB ProjectEstimate instances with a custom
 * equals() and hashCode() method such that equal ProjectEstimate instances are
 * those with the same name and owner.
 * 
 * @author Cam Moore
 * 
 */
public class EstimateStringMap {
  /** The internal map. */
  private Map<ProjectEstimate, String> estimate2String = new HashMap<ProjectEstimate, String>();

  /**
   * Puts [estimate, info] into the map, after removing any current estimate
   * instance from the map with the same name and owner.
   * 
   * @param estimate The ProjectEstimate to be added.
   * @param info The associated String.
   */
  public void put(ProjectEstimate estimate, String info) {
    this.remove(estimate);
    estimate2String.put(estimate, info);
  }
  
  /**
   * Returns the string associated with the estimate, or null if not found.
   * @param estimate The ProjectEstimate whose string is to be retrieved.
   * @return The string, or null if Project is not found in the map.
   */
  public String get(ProjectEstimate estimate) {
    String owner = estimate.getEstimator();
    String project = estimate.getProject();
    Set<ProjectEstimate> estimates = estimate2String.keySet();
    for (ProjectEstimate match : estimates) {
      if (match.getEstimator().equals(owner) && match.getProject().equals(project)) {
        return estimate2String.get(match);
      }
    }
//    throw new RuntimeException("Did not find project estimate for: " + name + " " + owner);
    return null;
  }

  /**
   * Removes any project estimates with the same name and owner as
   * ProjectEstimate from this data structure.
   * 
   * @param estimate An estimate specifying the projects to be removed by name and
   *          owner.
   */
  public void remove(ProjectEstimate estimate) {
    String owner = estimate.getEstimator();
    String project = estimate.getProject();
    List<ProjectEstimate> estimatesToRemove = new ArrayList<ProjectEstimate>();
    // First see if a ProjectEstimate with this name and owner exists in the internal map.
    Set<ProjectEstimate> oldEstimates = estimate2String.keySet();
    for (ProjectEstimate oldEstimate : oldEstimates) {
      if (oldEstimate.getEstimator().equals(owner) && oldEstimate.getProject().equals(project)) {
        estimatesToRemove.add(oldEstimate);
      }
    }
    // remove any estimates that matched
    for (ProjectEstimate estimateToRemove : estimatesToRemove) {
      estimate2String.remove(estimateToRemove);
    }
  }

  /**
   * Returns the strings in this map as a Collection.
   * @return The strings as a collection.
   */
  public Collection<String> values() {
    return estimate2String.values();
  }
}
